home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / python2.6 / dist-packages / gst-0.10 / gst / extend / jukebox.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  11.5 KB  |  300 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import sys
  6. import pickle
  7. import random as rand
  8. import gobject
  9. gobject.threads_init()
  10. import pygst
  11. pygst.require('0.10')
  12. import gst
  13. import utils
  14. from pygobject import gsignal
  15. import sources
  16. from leveller import Leveller
  17.  
  18. class Jukebox(gst.Bin):
  19.     gsignal('done', str)
  20.     gsignal('prerolled')
  21.     gsignal('changed', str, gobject.TYPE_UINT64)
  22.     gsignal('looped')
  23.     
  24.     def __init__(self, files, rms = 0.2, loops = 0, random = False, caps = 'audio/x-raw-int,channels=2,rate=44100', picklepath = 'level.pck'):
  25.         self.__gobject_init__()
  26.         self._target_rms = rms
  27.         self._loopsleft = loops
  28.         self._loopsdone = 0
  29.         self._random = random
  30.         self._picklepath = picklepath
  31.         self._caps = gst.caps_from_string(caps)
  32.         self._files = files[:]
  33.         self._levels = { }
  34.         self._prerolled = False
  35.         self._playing = False
  36.         self._scani = 0
  37.         self._playi = 0
  38.         self._lastadded = None
  39.         self._lastposition = long(0)
  40.         if not len(files) > 1:
  41.             raise TypeError, 'Must have at least 2 files'
  42.         len(files) > 1
  43.         self._composition = gst.element_factory_make('gnlcomposition')
  44.         self._composition.connect('pad-added', self._composition_pad_added_cb)
  45.         self.add(self._composition)
  46.         self._srcpad = None
  47.         if os.path.exists(self._picklepath):
  48.             file = open(self._picklepath)
  49.             self._levels = pickle.load(file)
  50.             file.close()
  51.         
  52.         if self._random:
  53.             self._files = rand.sample(self._files, len(self._files))
  54.         
  55.  
  56.     
  57.     def preroll(self):
  58.         gst.debug('starting jukebox prerolling')
  59.         self._scan()
  60.  
  61.     
  62.     def start(self):
  63.         if not self._prerolled:
  64.             raise Exception, 'baby'
  65.         self._prerolled
  66.         self.set_state(gst.STATE_PAUSED)
  67.  
  68.     
  69.     def _scan(self):
  70.         if self._scani >= len(self._files):
  71.             gst.debug("We're done scanning !")
  72.             return None
  73.         file = self._files[self._scani]
  74.         self._scani += 1
  75.         if file in self._levels.keys():
  76.             gst.debug('already did file %s' % file)
  77.             self._check_prerolled()
  78.             gobject.timeout_add(0, self._scan)
  79.             return None
  80.         gst.debug('creating leveller for %s' % file)
  81.         leveller = Leveller(file)
  82.         leveller.connect('done', self._leveller_done_cb, file)
  83.         gobject.timeout_add(0, leveller.start)
  84.  
  85.     
  86.     def _leveller_done_cb(self, l, reason, file):
  87.         if reason != sources.EOS:
  88.             gst.debug('Error: %s' % reason)
  89.             return None
  90.         gst.debug('in: %s, out: %s' % (gst.TIME_ARGS(l.mixin), gst.TIME_ARGS(l.mixout)))
  91.         gst.debug('rms: %f, %f dB' % (l.rms, l.rmsdB))
  92.         self._levels[file] = (l.rms, l.mixin, l.mixout, l.length)
  93.         gst.debug('writing level pickle')
  94.         file = open(self._picklepath, 'w')
  95.         pickle.dump(self._levels, file)
  96.         file.close()
  97.         self._check_prerolled()
  98.         self._scan()
  99.         gobject.timeout_add(0, l.clean)
  100.  
  101.     
  102.     def _new_gnl_source(self, location, start):
  103.         '''
  104.         Creates a new GnlSource containing an AudioSource with the following
  105.         properties correctly set:
  106.         _ volume level
  107.         _ priority
  108.         _ duration
  109.         The start position MUST be given
  110.         '''
  111.         if not self._levels[location]:
  112.             return None
  113.         self.debug('Creating new GnlSource at %s for %s' % (gst.TIME_ARGS(start), location))
  114.         idx = self._files.index(location) + self._loopsdone * len(self._files)
  115.         (rms, mixin, mixout, duration) = self._levels[location]
  116.         gnls = gst.element_factory_make('gnlsource', 'source-%d-%s' % (idx, location))
  117.         src = sources.AudioSource(location)
  118.         gnls.add(src)
  119.         level = 1
  120.         if rms > self._target_rms:
  121.             level = self._target_rms / rms
  122.             gst.debug('setting volume of %f' % level)
  123.         else:
  124.             gst.debug('not going to go above 1.0 level')
  125.         src.set_volume(level)
  126.         gnls.props.priority = 2 * self._loopsdone + 1 + idx % 2
  127.         gnls.props.start = long(start)
  128.         gnls.props.duration = long(duration)
  129.         gnls.props.media_duration = long(duration)
  130.         gnls.props.media_start = long(0)
  131.         return gnls
  132.  
  133.     
  134.     def _new_mixer(self, start, duration):
  135.         gnlo = gst.element_factory_make('gnloperation')
  136.         ad = gst.element_factory_make('adder')
  137.         gnlo.add(ad)
  138.         gnlo.props.sinks = 2
  139.         gnlo.props.start = start
  140.         gnlo.props.duration = duration
  141.         gnlo.props.priority = 0
  142.         return gnlo
  143.  
  144.     
  145.     def _append_file(self, location):
  146.         '''
  147.         Appends the given file to the composition, along with the proper mixer effect
  148.         '''
  149.         self.debug('location:%s' % location)
  150.         start = self._lastposition
  151.         if self._lastadded:
  152.             start += self._levels[self._lastadded][2]
  153.             start -= self._levels[location][1]
  154.         
  155.         gnls = self._new_gnl_source(location, start)
  156.         self._composition.add(gnls)
  157.         if self._lastadded:
  158.             duration = (self._levels[self._lastadded][3] - self._levels[self._lastadded][2]) + self._levels[location][1]
  159.             mixer = self._new_mixer(start, duration)
  160.             self._composition.add(mixer)
  161.         
  162.         self._lastposition = start
  163.         self._lastadded = location
  164.         self.debug('lastposition:%s , lastadded:%s' % (gst.TIME_ARGS(self._lastposition), self._lastadded))
  165.  
  166.     
  167.     def _check_prerolled(self):
  168.         gst.debug('_check_prerolled: index: scan %d, play %d' % (self._scani, self._playi))
  169.         if not (self._prerolled) and self._scani > self._playi + 1:
  170.             self._prerolled = True
  171.             self._append_file(self._files[0])
  172.             self._append_file(self._files[1])
  173.             self.debug('now prerolled and ready to play')
  174.             self.emit('prerolled')
  175.         
  176.  
  177.     
  178.     def _emit_changed(self, file, when):
  179.         print 'emitting changed for %s at %r' % (file, when)
  180.         self.emit('changed', file, when)
  181.  
  182.     
  183.     def _source_clean(self, source):
  184.         source.set_state(gst.STATE_NULL)
  185.         self.remove(source)
  186.         source.clean()
  187.  
  188.     
  189.     def _composition_pad_added_cb(self, comp, pad):
  190.         if self._srcpad:
  191.             return None
  192.         self.debug('Ghosting source pad %s' % pad)
  193.         self._srcpad = gst.GhostPad('src', pad)
  194.         self._srcpad.set_active(True)
  195.         self.add_pad(self._srcpad)
  196.  
  197.     
  198.     def do_handle_message(self, message):
  199.         self.debug('got message %s / %s / %r' % (message.src.get_name(), message.type.first_value_name, message))
  200.         gst.Bin.do_handle_message(self, message)
  201.  
  202.     
  203.     def do_state_change(self, transition):
  204.         if not self._prerolled:
  205.             gst.error('Call Jukebox.preroll() before!')
  206.             return gst.STATE_CHANGE_FAILURE
  207.         return gst.Bin.do_state_change(self, message)
  208.  
  209.  
  210. gobject.type_register(Jukebox)
  211.  
  212. def _find_elements_recurse(element):
  213.     if not isinstance(element, gst.Bin):
  214.         return [
  215.             element]
  216.     l = []
  217.     for e in element.elements():
  218.         l.extend(_find_elements_recurse(e))
  219.     
  220.     return l
  221.  
  222.  
  223. def _find_unconnected_pad(bin, direction):
  224.     for e in _find_elements_recurse(bin):
  225.         for p in e.pads():
  226.             if p.get_direction() == direction and not p.get_peer():
  227.                 return p
  228.         
  229.     
  230.  
  231. if __name__ == '__main__':
  232.     main = gobject.MainLoop()
  233.     pipeline = gst.Pipeline('jukebox')
  234.     list = open(sys.argv[1]).read().rstrip().split('\n')
  235.     print list
  236.     source = Jukebox(list, random = True, loops = 1)
  237.     
  238.     def _jukebox_prerolled_cb(jukebox):
  239.         print 'prerolled'
  240.         _start()
  241.  
  242.     
  243.     def _jukebox_changed_cb(jukebox, filename, when):
  244.         print 'changed file to %s at %s' % (filename, float(when) / gst.TIME_ARGS(gst.SECOND))
  245.  
  246.     
  247.     def _jukebox_looped_cb(jukebox):
  248.         print 'jukebox looped'
  249.  
  250.     
  251.     def _start():
  252.         source.start()
  253.         print 'setting pipeline to PLAYING'
  254.         pipeline.set_state(gst.STATE_PLAYING)
  255.         print 'set pipeline to PLAYING'
  256.  
  257.     
  258.     def jukebox_pad_added(comp, pad, sinkpad):
  259.         pad.link(sinkpad)
  260.  
  261.     
  262.     def jukebox_message(bus, message):
  263.         if message.type == gst.MESSAGE_ERROR:
  264.             print 'Error: %s' % message.parse_error()
  265.             main.quit()
  266.         elif message.type == gst.MESSAGE_EOS:
  267.             print 'done'
  268.             main.quit()
  269.         
  270.  
  271.     source.connect('prerolled', _jukebox_prerolled_cb)
  272.     source.connect('changed', _jukebox_changed_cb)
  273.     source.connect('looped', _jukebox_looped_cb)
  274.     source.preroll()
  275.     pipeline.add(source)
  276.     bus = pipeline.get_bus()
  277.     bus.add_signal_watch()
  278.     bus.connect('message', jukebox_message)
  279.     p = 'alsasink'
  280.     if len(sys.argv) > 2:
  281.         p = ' '.join(sys.argv[2:])
  282.     
  283.     print 'parsing output pipeline %s' % p
  284.     sinkbin = gst.parse_launch('bin.( %s )' % p)
  285.     pipeline.add(sinkbin)
  286.     apad = _find_unconnected_pad(sinkbin, gst.PAD_SINK)
  287.     if not apad:
  288.         raise TypeError, 'No unconnected sink pad found in bin %r' % sinkbin
  289.     apad
  290.     sinkpad = gst.GhostPad('sink', apad)
  291.     sinkbin.add_pad(sinkpad)
  292.     source.connect('pad-added', jukebox_pad_added, sinkpad)
  293.     print 'Going into main loop'
  294.     sys.stdout.flush()
  295.     main.run()
  296.     print 'Left main loop'
  297.     sys.stdout.flush()
  298.     pipeline.set_state(gst.STATE_NULL)
  299.  
  300.